using System;
using System.Collections.Generic;
using System.BusinessObjects.Data;
using Blazing.BusinessObjects.Queries;
using System.Xml.Serialization;
using Blazing.BusinessObjects.Tagging;
using Iesi.Collections.Generic;
using System.BusinessObjects.Validation;

namespace Blazing.BusinessObjects.Locations
{
    [Serializable]
	public class Location : DataObject<Location>
	{
        public virtual int ID
		{
			get
			{
				return GetValue<int>("ID");
			}
			set
			{
				BeginEdit();
				SetValue("ID", value);
			}
		}

        string _level = null;
        public virtual string LevelName
        {
            get 
            {
                if (string.IsNullOrEmpty(_level))
                {
                    _level = "";
                    Location ploc = ParentLocation;
                    while (ploc != null)
                    {
                        _level += "..";
                        ploc = ploc.ParentLocation;
                    }
                }
                return _level+Namelong;
            }
        }

        public virtual string Nameshort
		{
			get
			{
				return GetValue<string>("Nameshort");
			}
			set
			{
				BeginEdit();
				SetValue("Nameshort", value);
			}
		}

        public virtual string Namelong
		{
			get
			{
				return GetValue<string>("Namelong");
			}
			set
			{
				BeginEdit();
				SetValue("Namelong", value);
			}
		}

        public virtual string Abbr
		{
			get
			{
				return GetValue<string>("Abbr");
			}
			set
			{
				BeginEdit();
				SetValue("Abbr", value);
			}
		}

        [NonSerialized]
        Location _parent;
        public virtual Location ParentLocation
        {
            get
            {
                return _parent;
            }
            set
            {
                BeginEdit();
                _parent = value;
            }
        }

        [XmlIgnore]
        public virtual IList<Location> ChildLocations
        {
            get
            {
                return Search(QrySearchChildLocaions.Query(ID));
            }
        }

        [NonSerialized]
        private ISet<TaxonomyTag> _locationTaxonomyTags = new HashedSet<TaxonomyTag>();
        public virtual ISet<TaxonomyTag> LocationTaxonomyTags
        {
            get
            {
                return _locationTaxonomyTags;
            }
            set
            {
                BeginEdit();
                _locationTaxonomyTags = value;
            }
        }

        public Blazing.BusinessObjects.Cms.Geocode Geocode { get; set; }

        public virtual DateTime RowStamp
		{
			get
			{
				return GetValue<DateTime>("RowStamp");
			}
			set
			{
				SetValue("RowStamp", value);
			}
        }

        #region Custom Validation
        protected override void AddValidationRules()
        {
            validationRules.Add(new ValidationRule(ValidationRuleCanNotSetParentToSelf()));
        }

        public virtual ValidatorTemplate ValidationRuleCanNotSetParentToSelf()
        {
            System.Reflection.PropertyInfo parentInfo = GetType().GetProperty("ParentLocation");
            ValidatorTemplate parentIsNotSelf = delegate(out string propName, out string message)
            {
                propName = "ParentLocation";
                bool retval = true;
                message = string.Empty;
                object curVal = parentInfo.GetValue(this, null);
                if (curVal != null)
                {
                    if (((Location)curVal).ID == ID)
                    {
                        message = string.Format("Location's parent can not be set to itself #{0}", ID);
                        retval = false;
                    }
                }
                return retval;
            };

            return parentIsNotSelf;
        }
        #endregion
    }
}
